#ifndef _SERVO_BASE_H_
#define _SERVO_BASE_H_
#include <stdint.h>
#include <HardwareSerial.h>
#include <EEPROM.h>


typedef enum _ServoRet
{
	SERVO_RET_SUCCESS = 0,
	SERVO_RET_ERROR,
	SERVO_RET_UNSUPPORT,
	SERVO_RET_TIMEOUT,
	SERVO_RET_LIMITED
} ServoRet_t;


/**
* @brief:
* Servo base class for single servo.
*
* Real Angle = Target Angle + Offset
*/
class CServoBase
{
public:
	CServoBase() {}
	virtual ~CServoBase() {}

	virtual void Uninit() = 0;
	
	virtual bool IsOffsetSupport() = 0;
	virtual ServoRet_t SetAngle(uint16_t angle, uint32_t msec) = 0;
	virtual ServoRet_t GetAngle(uint16_t &angle) = 0;
	virtual ServoRet_t SetOffset(int16_t offset) = 0;
	virtual ServoRet_t GetOffset(int16_t &offset) = 0;
	virtual ServoRet_t SetId(uint8_t newid) = 0;
	virtual ServoRet_t SetLed(bool on) = 0;
	virtual ServoRet_t Terminate() = 0;
	virtual ServoRet_t GetFirmware(uint32_t &firmware) = 0;
	virtual ServoRet_t Lock() = 0;
	virtual ServoRet_t Unlock() = 0;
};


/**
* @brief:
* Bus servo.
* Changing id will invalides the instance of this class, because of mismatch id!
*/
class CServoBus : public CServoBase
{
public:
	CServoBus();
	virtual ~CServoBus();

	virtual ServoRet_t Init(uint8_t id, HardwareSerial *serl, int waitMsec = 10);
	virtual void Uninit();
 
protected:
	uint8_t m_id;
	HardwareSerial *m_serlPtr;
	int m_waitMsec;
};


/**
* @brief:
* PWM servo
*/
class CServoPWM : public CServoBase
{
public:
	CServoPWM();
	virtual ~CServoPWM();

	virtual ServoRet_t Init(int pin);
	virtual void Uninit();

protected:
	int m_pin;
};

#endif

